package utils
{
	import flash.utils.ByteArray;

	public class CryptoUtil
	{
		/**
		 * 加密指定的加密源bytes，并生成16byte校验加密bytes
		 * @param socketDataStructureType 数据包种类标识
		 * @param connectionID 连接ID
		 * @param connectionCheckCode 连接校验码
		 * @param packetNumber 包序号
		 * @param packetBytes 包体bytes
		 * @param keys 加解的key
		 * @return 成功生成的校验码
		 */
		public static function encryptPacket(socketDataStructureType:int, connectionID:int, connectionCheckCode:int, packetNumber:int, packetBytes:ByteArray, key:Array):ByteArray
		{
//			trace("加密：socketDataStructureType:"+socketDataStructureType+" connectionID:"+connectionID+" connectionCheckCode:"+connectionCheckCode+" packetNumber:"+packetNumber+" key:"+key.toString());
			var	sumValue:int=socketDataStructureType+connectionID+connectionCheckCode+packetNumber+packetBytes.length+key.length;
//			trace("sumValue1:"+sumValue);
			var t:int;
			var o:int;
			var i:int=0;
			var j:int = 0;
			var l:int = packetBytes.length;
			var keys:Array = key.slice(0, 256);
			for(var c:int=0; c<l; c++)
			{
				i = (i+1) % 256;
				j = (j+keys[i]) % 256;
				
				t = keys[j];
				keys[j] = keys[i];
				keys[i] = t;
				
				o = keys[(keys[i] + keys[j]) % 256];
				sumValue+=int(packetBytes[c] & 0xFF);
				packetBytes[c] = (packetBytes[c] ^ o);
			}
//			trace("sumValue2:"+sumValue);
			var sumValueByteArray:ByteArray=ByteUtil.getBytesByInt(sumValue);
			
			var baStr:String="";
			for(i=0;i<sumValueByteArray.length;i++)
			{
				baStr+=", "+sumValueByteArray[i];
			}
//			trace("sumValueByteArray:"+baStr);
			
			RC4Util.crypto(sumValueByteArray, key);
			return sumValueByteArray;
		}
		
		/**
		 * 解密指定的加密源bytes，并生成16byte校验加密bytes
		 * @param socketDataStructureType 数据包种类标识
		 * @param connectionID 连接ID
		 * @param connectionCheckCode 连接校验码
		 * @param packetNumber 包序号
		 * @param packetBytes 加密源bytes
		 * @param keys 加解的key
		 * @return 成功生成的4byte校验加密bytes
		 */
		public static function decryptionPacket(socketDataStructureType:int, connectionID:int, connectionCheckCode:int, packetNumber:int, packetBytes:ByteArray, key:Array):ByteArray
		{
//			trace("解密：socketDataStructureType:"+socketDataStructureType+" connectionID:"+connectionID+" connectionCheckCode:"+connectionCheckCode+" packetNumber:"+packetNumber+" key:"+key.toString());
			var sumValue:int=socketDataStructureType+connectionID+connectionCheckCode+packetNumber+packetBytes.length+key.length;
//			trace("sumValue1:"+sumValue);
			var t:int;
			var o:int;
			var i:int=0;
			var j:int = 0;
			var l:int = packetBytes.length;
			var keys:Array = key.slice(0, 256);
			for(var c:int=0; c<l; c++)
			{
				i = (i+1) % 256;
				j = (j+keys[i]) % 256;
				
				t = keys[j];
				keys[j] = keys[i];
				keys[i] = t;
				o = keys[(keys[i] + keys[j]) % 256];
				packetBytes[c] = (packetBytes[c] ^ o);
				sumValue+=int(packetBytes[c] & 0xFF);
			}
//			trace("sumValue2:"+sumValue);
			var sumValueByteArray:ByteArray=ByteUtil.getBytesByInt(sumValue);
			
			var baStr:String="";
			for(i=0;i<sumValueByteArray.length;i++)
			{
				baStr+=", "+sumValueByteArray[i];
			}
//			trace("原sumValueByteArray:"+baStr);
			
			RC4Util.crypto(sumValueByteArray, key);
			
			baStr="";
			for(i=0;i<sumValueByteArray.length;i++)
			{
				baStr+=", "+sumValueByteArray[i];
			}
//			trace("解后sumValueByteArray:"+baStr);
			
			return sumValueByteArray;
		}
		
		/**
		 * 生成随机字符串
		 * @param length 指定的随机产生的长度
		 * @return  随机产生的字符串
		 */
		public static function genRandomString(length:int):String
		{
			var ran:int;
			var number:int;
			var code:String;
			var checkCode:String="";
			var i:int;

			for (i=0; i<length; i++)
			{
				ran=Math.round(Math.random()*2);
				number=Math.round(Math.random()*10000);
				if (ran==0) {
					code = String.fromCharCode(48+(number % 10));
				} else if (ran==1) {
					code = String.fromCharCode(65+(number % 26)) ;
				} else {
					code = String.fromCharCode(97+(number % 26)) ;
				}
				
				checkCode+=code;
			}
			return checkCode;
		}
	}
}